﻿namespace Atomic.Events
{
    using System.Linq;
    using System.Threading.Tasks;

    using Atomic.Extensions;

    /// <summary>
    /// 默认事件分发器
    /// </summary>
    /// <typeparam name="TEvent">事件类型</typeparam>
    public class DefaultEventDispatcher<TEvent> : EventDispatcherBase<TEvent> where TEvent : IEvent
    {
        /// <summary>
        /// 主事件处理器数组。
        /// </summary>
        private IEventHandler<TEvent>[] _masterEventHandlers = null;

        /// <summary>
        /// 子事件处理器数组。
        /// </summary>
        private IEventHandler<TEvent>[] _childEventHandlers = null;

        /// <summary>
        /// 初始化事件分发器
        /// </summary>
        /// <param name="eventHandlerGroup">事件处理器组</param>
        public DefaultEventDispatcher(IEventHandlerGroup<TEvent> eventHandlerGroup)
            : base(eventHandlerGroup)
        {
        }

        /// <summary>
        /// 处理事件
        /// </summary>
        /// <param name="event">事件信息</param>
        protected override void OnHandle(TEvent @event)
        {
            //执行主处理器并返回处理结果。
            var complete = this.GetMasterEventHandlers().Select(masterEventHandler => masterEventHandler.Handle(@event)).All(eventResult => eventResult == true);

            //只要有一个处理器处理失败，则代表操作处理失败，将不会开启子处理器进行处理。
            if (complete)
            {
                //异步并行执行子处理器。
                this.GetChildEventHandlers().ForEachParallel(childEventHandler => childEventHandler.Handle(@event));
            }
        }

        /// <summary>
        /// 获取所有主事件处理器。
        /// </summary>
        /// <returns>事件处理器数组</returns>
        private IEventHandler<TEvent>[] GetMasterEventHandlers()
        {
            if (this._masterEventHandlers == null || !this._masterEventHandlers.Any())
            {
                this._masterEventHandlers = this._eventHandlerGroup.GetMasterEventHandlers().ToArray();
            }

            return this._masterEventHandlers;
        }

        /// <summary>
        /// 获取所有子事件处理器。
        /// </summary>
        /// <returns>事件处理器数组</returns>
        private IEventHandler<TEvent>[] GetChildEventHandlers()
        {
            if (this._childEventHandlers == null || !this._childEventHandlers.Any())
            {
                this._childEventHandlers = this._eventHandlerGroup.GetChildEventHandlers().ToArray();
            }

            return this._childEventHandlers;
        }
    }
}